<?php

use Illuminate\Support\Facades\Redirect;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Token;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Symfony\Component\HttpFoundation\JsonResponse;

/*
|--------------------------------------------------------------------------
| Application & Route Filters
|--------------------------------------------------------------------------
|
| Below you will find the "before" and "after" events for the application
| which may be used to do any work before or after a request into your
| application. Here you may also register your custom route filters.
|
*/

App::before(function($request)
{

		if ($request->is('admins*'))
    {
    	Config::set('auth.model', 'Employee');
    	Config::set('auth.table', 'employee');
    }

    // ip whitelist
 //    $ips = Config::get('app.whitelisted_ips');
 //    $negotiator = new \Negotiation\Negotiator();
	// $priorities = array('application/json');
 //    $mediaType = $negotiator->getBest($request->header('Accept'), $priorities);
 //    if (is_object($mediaType) && ($mediaType->getValue() == 'application/json') && !in_array($request->ip(), $ips)) {
 //        return Response::view(
 //            'errors.403_json',
 //            array('data' => '没有权限访问这个接口')
 //        )->header(
 //        	'Content-Type', 'application/json'
 //        )->setStatusCode(403);
 //    }

    // rate limiting control
    $username = "";
    if (Auth::check()) {
    	$username = Auth::user()->username;
    }
    if (RateLimit::reachesRateLimit($request->method(), $request->url(), $request->ip(), $username, 60, 200)
    	|| RateLimit::reachesRateLimit($request->method(), $request->url(), $request->ip(), $username, 60*60, 1000)) {
    	Log::error(sprintf("User with ip address: '%s' and username: '%s' has exceeded the rate limit of url: '%s'.", $request->ip(), $username, $request->url()));
		return Response::view(
            'errors.429_json',
            array('data' => '一定的时间内访问接口次数上限已到，请稍后再试')
        )->header(
        	'Content-Type', 'application/json'
        )->setStatusCode(429);
    } else {
    	RateLimit::logAccess($request->method(), $request->url(), $request->ip(), $username);
    }

    // content negotiation
    $negotiator = new \Negotiation\Negotiator();
    $priorities   = array('text/html', 'application/json');

    $acceptHeader = $request->header('Accept');
    $mediaType = $negotiator->getBest($acceptHeader, $priorities);
	if ($mediaType) {
		$responseType = $mediaType->getValue();
	} else {
		$responseType = 'text/html';
	}
	Config::set('response.content_type', $responseType);
});


App::after(function($request, $response)
{
//	try{
//		$response->header("Access-Control-Allow-Origin", "*");
//		$response->header("Access-Control-Allow-Headers", "Authorization,X-Requested-With,Accept,Content-Type");
//		$response->header("Access-Control-Expose-Headers", "Authorization");
//	}catch(Exception $e){}

	//if (!is_a($response, "Symfony\\Component\\HttpFoundation\\BinaryFileResponse")) {
		$response->headers->set("Access-Control-Allow-Origin", "*");
		$response->headers->set("Access-Control-Allow-Headers", "Authorization,X-Requested-With,Accept,Content-Type");
		$response->headers->set("Access-Control-Expose-Headers", "Authorization");
	//}

	// $token = JWTAuth::getToken();
	// if ($response->getStatusCode() !== 401 && $token) {
	// 	$token = JWTAuth::parseToken()->refresh();
	// 	$response->header("Authorization", "bearer " . $token);

	// 	DB::table('user')->where('id', '=',Auth::user()->id )->update(array(
	// 	    'last_login' => date("Y-m-d H:i:s"),
	// 	    'login_token' => $token
	// 	));
	// }
});

/*
|--------------------------------------------------------------------------
| Authentication Filters
|--------------------------------------------------------------------------
|
| The following filters are used to verify that the user of the current
| session is logged into this application. The "basic" filter easily
| integrates HTTP Basic authentication for quick, simple checking.
|
*/

Route::filter('auth', function($request)
{
	// 看看用户是否提供了Basic Auth的header
	if (Input::getUser()) {
		if (preg_match ( "/^1[3-8]\d{9}$/", Input::getUser() )) {
			return Auth::onceBasic('phone');
		} else {
			return Auth::onceBasic('email');
		}
	}
	
	// 看看能不能用JWT来认证用户
    $token = JWTAuth::getToken();
    if (is_object($token)) {
	    try{
	       $user = JWTAuth::toUser($token);
	       $tokenStr = $token->__toString();
	       if ($user->login_token != $tokenStr){
	       		throw new Exception("登录Token不匹配");
	       }

	       // 设置已经登录的用户，但是不保存在session里面
	       Auth::setUser($user);
	       return;
	    } 
	    catch(TokenExpiredException $e) {
	        return Response::view(
	            'errors.401_json',
	            array('data' => array( 'error' => $e->getMessage(), 'code' => '401_1'))
            )->header(
            	'Content-Type', 'application/json'
            )->setStatusCode(401);
	     }
	      // catch(JWTException $e) {
	        // return Response::view(
	        //     'errors.' . $e->getStatusCode() . '_json',
	        //     array('data' => $e->getMessage())
         //    )->header(
         //    	'Content-Type', 'application/json'
         //    )->setStatusCode($e->getStatusCode());
	     // } 
	    catch(Exception $e){
	        return Response::view(
	            'errors.401_json',
	            array('data' => array( 'error' => 'Invalid Session', 'code' => '401_2'))
            )->header(
            	'Content-Type', 'application/json'
            )->setStatusCode(401); // Token expired/invalid (Esri)
	    }
	} else {
	// 看看能不能用cookies来认证用户
		if (Auth::guest() && !Auth::viaRemember() )
		{
			if (Config::get('response.content_type') == "application/json")
			{
		        return Response::view(
		            'errors.401_json',
		            array('data' => '资源没有登录不能访问')
	            )->header(
	            	'Content-Type', 'application/json'
	            )->setStatusCode(401);
			}
			else
			{
				$backurl = $_SERVER["REQUEST_URI"];
				return Redirect::route('home.login', compact("backurl"));
			}
		}
	}
	
    // return Response::view(
    //     'errors.401_json',
    //     array('data' => '资源没有登录不能访问')
    // )->header(
    // 	'Content-Type', 'application/json'
    // )->setStatusCode(401);
});

Route::filter('optional_auth', function()
{
	if (Input::getUser()) {
		if (preg_match ( "/^1[3-8]\d{9}$/", Input::getUser() )) {
			return Auth::onceBasic('phone');
		} else {
			return Auth::onceBasic('email');
		}
	}


	// 看看能不能用JWT来认证用户
    $token = JWTAuth::getToken();
    if (is_object($token)) {
	    try{
	       $user = JWTAuth::toUser($token);
	       $tokenStr = $token->__toString();
	       if ($user->login_token != $tokenStr){
	       		throw new Exception("登录Token不匹配");
	       }

	       // 设置已经登录的用户，但是不保存在session里面
	       Auth::setUser($user);
	       return;
	    } catch(Exception $e){
	    }
	}
});

Route::filter('token_auth', function()
{
	// 看看能不能用JWT来认证用户
    $token = JWTAuth::getToken();
    if (is_object($token)) {
	    try{
	       $user = JWTAuth::toUser($token);
	       $tokenStr = $token->__toString();
	       if ($user->login_token != $tokenStr){
	       		throw new Exception("登录Token不匹配");
	       }

	       // 设置已经登录的用户，但是不保存在session里面
	       Auth::setUser($user);
	       return;
	    } catch(Exception $e){
	    }
	}
});

Route::filter('lawyer', function()
{
	if (!Auth::user()->isVerifiedLawyer()) {
		switch (Config::get('response.content_type')) {
	        case 'application/json':
	            return Response::view(
	            	'errors.403_json',
	            	array('data' => '你没有权限访问这个接口，因为你不是律师.')
	            )->header(
	            	'Content-Type', 'application/json'
	            )->setStatusCode(403);
	        	break;
	        case 'text/html':
	        default:
			    return Redirect::route('center.customer.become_lawyer');
	        	break;
		}
	}
});

Route::filter('customer', function()
{
    if (Auth::user()->isPendingVerification()) {
		switch (Config::get('response.content_type')) {
	        case 'application/json':
	            return Response::view(
	            	'errors.403_json',
	            	array('data' => '你没有权限访问这个接口，因为你已经提交了称为律师的请求，或者你已经是一个律师了。')
	            )->header(
	            	'Content-Type', 'application/json'
	            )->setStatusCode(403);
	        	break;
	        case 'text/html':
	        default:
    			return Redirect::route('center.lawyer.info');
	        	break;
		}
    }
});

/*
|--------------------------------------------------------------------------
| Guest Filter
|--------------------------------------------------------------------------
|
| The "guest" filter is the counterpart of the authentication filters as
| it simply checks that the current user is not logged in. A redirect
| response will be issued if they are, which you may freely change.
|
*/

Route::filter('guest', function()
{
	if (Auth::check()) return Redirect::to('/');
});

/*
|--------------------------------------------------------------------------
| CSRF Protection Filter
|--------------------------------------------------------------------------
|
| The CSRF filter is responsible for protecting your application against
| cross-site request forgery attacks. If this special token in a user
| session does not match the one given in this request, we'll bail.
|
*/
	
Route::filter('csrf', function()
{
	// 检查登录session是否存在。如果存在，就证明不是Basic Auth登录或者JWT登录，就要验证csrf token。
	// $isBearerTokenAuth = is_object(JWTAuth::getToken());
	// $isBasicAuth = (bool)Input::getUser();
	// $hasAuthToken = ($isBearerTokenAuth || $isBasicAuth);
	// $isValidatedMethod = in_array(Input::server ( 'REQUEST_METHOD' ), array('POST', 'DELETE', 'PUT'));
	// if ($isValidatedMethod && !$hasAuthToken && Session::token() !== Input::get('_token'))
	// {
	// 	return Response::view(
 //            'errors.403_json',
 //            array('data' => '没有权限进行访问')
 //        )->header(
 //        	'Content-Type', 'application/json'
 //        )->setStatusCode(403);
	// 	// throw new Illuminate\Session\TokenMismatchException;
	// }
});

/**
 * 基于路由缓存请求的response
 */
Route::filter('cache', function($route, $request, $response = null) {
	// Do not cache if the debug is true
	if(! Config::get('app.debug')) {
		$key = Str::slug(Request::fullUrl());
		if(is_null($response) && Cache::has($key)) {
			$data = Cache::get($key);
			$data = json_decode($data, true);
			$response = Response::make($data['content'], $data['status_code']);
			$response->header('Content-Type', 'application/json');
			return $response;
		} elseif(!is_null($response) && !Cache::has($key)) {
			// Cache for 1 hours
			$cache = json_encode(['content' => $response->getContent(), 'status_code' => $response->getStatusCode()]);
			Cache::put($key, $cache, 60);
		}
	}
});

